package ru.dcsearch.indexer;

/***************************************************************************
 *   Modified by TMC
 *   berechitai@gmail.com
 *
 *   This file is part of DC Indexer project
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 ***************************************************************************/
/*
 *  Mobile DC - a DirectConnect client written in Java and designed for
 *  the Sony Ericsson p800/p900 or equivalent Symbian OS 7.0 platforms
 *  Copyright (C) 2004 Conrad Helgesson, vakum@home.se
 *
 *  This file is part of Mobile DC.
 *
 *  Mobile DC is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  Mobile DC is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Mobile DC; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


import java.util.Vector;
import java.util.Hashtable;

public class Userlist {

	final static char COMMAND_SEP_CHAR = ' ';
	final static char COMMAND_BEG_CHAR = '$';

	private Vector<String> slItems;
	private Hashtable<String,String> OPs, ShareString;
	private Hashtable<String,Userinfo> USERs;
	
	
	private int SelectedItem;
	private DCClient mw;

	private long		totalShare;
	public boolean		hasNicklist;
	private int lastUserCount = 0;

	//::Create new mDClist
	public Userlist(DCClient m, Prefs pr) {
		mw = m;

		//yInset = 14;
		slItems = new Vector<String>();
		USERs = new Hashtable<String,Userinfo>();
	    OPs = new Hashtable<String,String>();
	    ShareString = new Hashtable<String,String>();
	    hasNicklist = false;
		totalShare = 0;
		
	}


	//::Return item at index idx
	public String getSelectedItem() {
		return slItems.elementAt(SelectedItem);
	}

	//::Return item at index idx
	public String getItem(int idx) {
		return slItems.elementAt(idx);
	}

	//::Return item at index idx
	public int getSelectedIndex() {
		if(SelectedItem+1 > slItems.size()) return -1;
		return SelectedItem;
	}

	//::Remove all items
	public void removeAll() {
		
		slItems.removeAllElements();
		SelectedItem = -1;

	}

	//::Get the number of items
	public int getItemCount() {
		return slItems.size();
	}

	public void select(int idx) {
		SelectedItem = idx;

	}

	//::Remove item
	public void remove(String s) {
		if(!slItems.contains(s)) return;
		if(slItems.indexOf(s) <= SelectedItem && SelectedItem != -1) SelectedItem -= 1;
		slItems.removeElement(s);

	}
	


	//::Add item
	public void add(String s) {
		add(s, 0);
	}

	//::Add item
	public void add(String s, int idx) {
		if(s.length() == 0) return;
		if(idx <= SelectedItem && SelectedItem != -1) SelectedItem += 1;
		slItems.insertElementAt(s, idx);
		
	}




	//::                             START OF USERLIST KINDA.


	public boolean IsOP(String op) { return OPs.containsKey(op); }
	public boolean IsUSER(String user) { return USERs.containsKey(user); }
	public String getDesc(String user) { return IsUSER(user)? USERs.get(user).desc:""; }
	public String getShare(String user) { return IsUSER(user)?""+ USERs.get(user).share:""; }
	public String getEmail(String user) { return IsUSER(user)? USERs.get(user).email:""; }
	public String getSpeed(String user) { return IsUSER(user)? USERs.get(user).speed:""; }


	//::Add MyINFO String data of this user. String: $ALL <nick> <interest>$ $<speed>$<e-mail>$<sharesize>$
	public void PutINFO(String s)
	{
		//new way , faster?
		String curUser;
		String curDesc;
		String curSpeed;
		String curEmail;
		String curShare;

		int curi = 5;
		int    i = s.indexOf(COMMAND_SEP_CHAR, curi);

		//substract data from the myinfostring
		if(i == -1) return;
		curUser = s.substring(curi, i);
		curi += 1+curUser.length();
		i = s.indexOf(COMMAND_BEG_CHAR, curi);
		if(i == -1) return;
		curDesc = s.substring(curi, i);
		curi += 3+curDesc.length();
		i = s.indexOf(COMMAND_BEG_CHAR, curi);
		if(i == -1) return;
		curSpeed = s.substring(curi, i-1); //watch it here
		curi += 2+curSpeed.length(); //watch it here
		i = s.indexOf(COMMAND_BEG_CHAR, curi);
		if(i == -1) return;
		curEmail = s.substring(curi, i);
		curi += 1+curEmail.length();
		i = s.indexOf(COMMAND_BEG_CHAR, curi);
		if(i == -1) return;
		curShare = s.substring(curi, i);

		//curShareOnlyContainsDigits-check
		i = curShare.length();
		long newShare = 0;
		if(i != 0) {
			boolean valid = true;
			for(int a=0;a<i;a++) {
				if(!(curShare.charAt(a) >= '0' && curShare.charAt(a) <= '9')) {
					valid = false;
					break;
				}
			}
			if(valid) newShare = Long.parseLong(curShare);
		}

		//remove old share from totalshare, if such exists
		if(USERs.containsKey(curUser)) {
			totalShare -= USERs.get(curUser).share;
			USERs.remove(curUser);
		} else { //User is logging in
			Logger.printUsersLog("*** User went online: "+curUser);
		}

		if(mw.nw.NoHello) {
			if(!USERs.containsKey(curUser)) AddUser(curUser);
			else AddSorted(curUser);
		}

		//add the info
		USERs.put(curUser, new Userinfo(curDesc, curSpeed, curEmail, newShare, curDesc.indexOf(",M:A,") != -1));
		totalShare += newShare;
		ShareString.put(curUser, Fix(newShare));
		
		Logger.printUsersLog("User added. Total: "+ USERs.size());
	}

	//::Process the big bauta userlist
	public void ProcessNicklist(String nicklist)
	{
		ClearData(false);
		removeAll();
		totalShare = 0;
		updateUstatus();
		String curUser;
		int curIndex = 0;
		if(mw.p.ulstmyinfo && !mw.nw.NoGetINFO) {
			while (nicklist.length() != curIndex) {
				curUser = nicklist.substring(curIndex,nicklist.indexOf("$$", curIndex));
				curIndex = nicklist.indexOf("$$", curIndex)+2;
				AddSorted(curUser);
				mw.nw.sendCommand("$GetINFO",curUser+COMMAND_SEP_CHAR+mw.p.getMynick());
			}
		} else {
			while (nicklist.length() != curIndex) {
				curUser = nicklist.substring(curIndex,nicklist.indexOf("$$", curIndex));
				curIndex = nicklist.indexOf("$$", curIndex)+2;
				AddSorted(curUser);
			}
		}
		hasNicklist = true;
	}

	// Add a user to the userlist.
	public void AddSorted(String curUser)
	{
		if(slItems.contains(curUser)) return;
		int numItems = getItemCount();
		boolean curIsOP = OPs.containsKey(curUser);

		if(mw.p.ulstsort) {
			if(numItems == 0) {
				add(curUser, 0);
				return;
			}
			int index = 0;
			if(!curIsOP) index = OPs.size();
			int compareValue = 0;
			boolean added = false;
			while((index < numItems) && !added) {
				if(curIsOP && !IsOP(getItem(index))) {
					added = true;
					add(curUser, index);
					break;
				}
				compareValue = curUser.toLowerCase().compareTo(getItem(index).toLowerCase());
				if(compareValue < 0) {
					added = true;
					add(curUser, index);
				}
				index++;
			}
			if(!added) add(curUser, numItems);
		} else {
			if(!curIsOP) add(curUser, numItems);
			else add(curUser, 0);
		}
	}

	//::Adds an Operator
	public void AddOP(String op_user)
	{
		if(!OPs.containsKey(op_user)) {
			OPs.put(op_user,"");
			remove(op_user);
			if(hasNicklist) AddSorted(op_user);
		}
	}


	//::Adds a user
	public void AddUser(String a_user)
	{
		
		if(hasNicklist) AddSorted(a_user);
	}


	//::Deletes a user
	public void DelUser(String d_user)
	{
		
		if(hasNicklist) {
			if(OPs.containsKey(d_user)) OPs.remove(d_user);
			remove(d_user);
			if(!USERs.containsKey(d_user)) {
				return;
			}
			totalShare -= USERs.get(d_user).share;
			USERs.remove(d_user);
			Logger.printUsersLog("User removed. Total: "+ USERs.size());
		} else {
			
			Logger.printUsersLog("User removed. Total: "+ USERs.size());
			
		}
	}


	//::Clear Hashtable, integers
	public void ClearData(boolean OP)
	{
		SelectedItem = -1;
		removeAll();
		USERs.clear();
		if(OP) OPs.clear();
		hasNicklist = false;
		totalShare = 0;
	}


	//::
	public void updateUstatus()
	{
		
		if(lastUserCount != getItemCount()) {
			lastUserCount = getItemCount();
			
		}
	}

	//::Convert bytes-integer to KiB or MiB etc.
	public String Fix(long value)
    {
    	java.text.DecimalFormat fmt = new java.text.DecimalFormat("####.##");
    	double size = 0;
    	if(value < 1024) return value + " B";
    	size = (double)value/1024;
    	if(size < 1024) return fmt.format(size) + " KiB";
    	size /= 1024;
    	if(size < 1024) return fmt.format(size) + " MiB";
    	size /= 1024;
    	if(size < 1024) return fmt.format(size) + " GiB";
    	size /= 1024;
    	return fmt.format(size) + " TiB";
    }


	//::This class handles all other userinfo...
	private class Userinfo {

		public Userinfo(String desc, String speed, String email, long share, boolean isA)
		{
			this.desc = desc;
			this.speed = speed;
			this.email = email;
			this.share = share;
			this.isA = isA;
		}
		String desc;
		String speed;
		String email;
		long share;
		boolean isA;
	}



}
